package utils

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
)

// RequestOptions 定义请求选项结构体
type RequestOptions struct {
	Method  string      // HTTP 请求方法，如 GET、POST 等
	URL     string      // 请求的 URL
	Payload interface{} // 请求的有效负载（JSON 数据）
	Headers map[string]string
}

// SendRequest 通用的网络请求发送函数
func SendRequest(options *RequestOptions) ([]byte, error) {
	var payloadReader io.Reader
	if options.Payload != nil {
		// 将有效负载转换为 JSON 字节切片
		payloadBytes, err := json.Marshal(options.Payload)
		if err != nil {
			return nil, fmt.Errorf("failed to marshal payload: %w", err)
		}
		payloadReader = bytes.NewBuffer(payloadBytes)
	}
	// 创建 HTTP 请求
	req, err := http.NewRequest(options.Method, options.URL, payloadReader)
	if err != nil {
		return nil, fmt.Errorf("failed to create request: %w", err)
	}
	// 设置请求头
	if options.Headers != nil {
		for key, value := range options.Headers {
			req.Header.Set(key, value)
		}
	}
	// 默认设置 Content-Type 为 application/json
	if req.Header.Get("Content-Type") == "" && options.Payload != nil {
		req.Header.Set("Content-Type", "application/json")
	}
	// 发送请求
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("failed to send request: %w", err)
	}
	defer resp.Body.Close()
	// 读取响应体
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("failed to read response body: %w", err)
	}
	// 检查响应状态码
	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
		return nil, fmt.Errorf("request failed with status code %d: %s", resp.StatusCode, string(body))
	}
	return body, nil
}

func Post(url string, payload interface{}) (string, error) {

	var options *RequestOptions
	options = &RequestOptions{
		Method:  "POST",
		URL:     url,
		Payload: payload,
		Headers: map[string]string{
			"Content-Type": "application/json",
		},
	}
	options.Method = "POST"
	if options.Headers["Content-Type"] == "" && options.Payload != nil {
		options.Headers["Content-Type"] = "application/json"
	}
	postBody, err := SendRequest(options)
	return string(postBody), err
}
